﻿using Microsoft.Extensions.Logging;
using PLCS.Application.Contracts.UserApp;
using PLCS.Application.Contracts.UserApp.Dtos;
using PLCS.Domain.Menus;
using PLCS.Domain.Roles;
using PLCS.Domain.Users;
using Volo.Abp.Domain.Repositories;

namespace PLCS.Application.UserApp;

public class UserAppService : ApplicationService, IUserAppService
{
    private readonly IRepository<User> _userRepository;
    private readonly IRepository<Menu> _menuRepository;
    private readonly IRepository<Role> _roleRepository;
    private readonly ILogger<UserAppService> _logger;

    public UserAppService(IRepository<User> userRepository,
        IRepository<Menu> menuRepository,
        IRepository<Role> roleRepository,
        ILogger<UserAppService> logger)
    {
        _userRepository = userRepository;
        _menuRepository = menuRepository;
        _roleRepository = roleRepository;
        _logger = logger;
    }

    /// <summary>
    /// 修改密码
    /// </summary>
    /// <param name="userChangePassWordDto"></param>
    /// <returns></returns>
    public async Task ChangePassword(UserChangePassWordDto userChangePassWordDto)
    {
        if (userChangePassWordDto.NewPassWord != userChangePassWordDto.NewPassWordAgain)
            throw new Exception("两次密码输入不一致");

        var user = await _userRepository.GetAsync(x => x.UserName == userChangePassWordDto.UserName);

        bool passres = user.CheckPassWord(userChangePassWordDto.OldPassWord);
        if (!passres)
            throw new Exception("原密码错误");
        user.ChangePassWord(userChangePassWordDto.NewPassWord);
        await _userRepository.UpdateAsync(user);
    }

    /// <summary>
    /// 开发者权限的创建用户（与注册不同）
    /// </summary>
    /// <param name="userEditDto"></param>
    /// <returns></returns>
    public async Task CreateAsync(UserEditDto userEditDto)
    {
        var user = await _userRepository.FindAsync(x => x.UserName == userEditDto.UserName);

        if (user != null)
            throw new Exception("用户名已存在");

        if (!string.IsNullOrEmpty(userEditDto.RolesString))
            user = new User(userEditDto.Name, userEditDto.UserName, "123456", userEditDto.RolesString);
        else
            user = new User(userEditDto.Name, userEditDto.UserName, "123456");
        _logger.LogInformation($"开发者权限创建修改密码成功，用户名{userEditDto.UserName}");
        await _userRepository.InsertAsync(user);
    }

    /// <summary>
    /// 根据ID删除用户
    /// </summary>
    /// <param name="Id"></param>
    /// <returns></returns>
    public async Task DeleteAsync(Guid Id)
    {
        await _userRepository.DeleteAsync(x => x.Id == Id);
    }

    /// <summary>
    /// 获取所有集合
    /// </summary>
    /// <returns></returns>
    public async Task<IEnumerable<UserDto>> GetListAsync()
    {
        var res = await _userRepository.GetListAsync();

        return ObjectMapper.Map<IEnumerable<User>, IEnumerable<UserDto>>(res);
    }

    /// <summary>
    /// 登录
    /// </summary>
    /// <param name="userLoginDto"></param>
    /// <returns></returns>
    ///
    public async Task<UserDto> Login(UserLoginDto userLoginDto)
    {
        var user = await _userRepository.FindAsync(x => x.UserName == userLoginDto.UserName);

        if (user == null)
            throw new Exception("用户名或密码错误");

        var res = user.CheckPassWord(userLoginDto.Password);
        if (!res)
            throw new Exception("用户名或密码错误");

        if (user.RolesString == "开发者")
        {
            user.Menus = await _menuRepository.GetListAsync(x => x.Parent == null);
            foreach (var item in user.Menus)
            {
                item.Children = await _menuRepository.GetListAsync(x => x.Parent == item);
            }
        }
        else
        {
            // 先通过用户找权限
            var rolelist = user.Analysis();
            user.Roles = new List<Role>();

            foreach (var item in rolelist)
            {
                var role = await _roleRepository.FindAsync(x => x.RoleName == item);
                user.Roles.Add(role);
            }

            // 再通过权限找菜单
            user.Menus = new List<Menu>();
            foreach (var item in user.Roles)
            {
                var menulist = item.Analysis();
                item.Menus = new List<Menu>();
                foreach (var menuitem in menulist)
                {
                    var menu = await _menuRepository.FindAsync(x => x.Title == menuitem);
                    foreach (var chilitem in await _menuRepository.GetListAsync())
                    {
                        chilitem.Children = await _menuRepository.GetListAsync(x => x.Parent == chilitem);
                    }
                    //去重
                    if (!user.Menus.Contains(menu))
                        user.Menus.Add(menu);
                }
            }
        }
        return ObjectMapper.Map<User, UserDto>(user);
    }

    /// <summary>
    /// 注册
    /// </summary>
    /// <param name="userRegisterDto"></param>
    /// <returns></returns>
    public async Task Register(UserRegisterDto userRegisterDto)
    {
        if (userRegisterDto.Password != userRegisterDto.PasswordAgain)
            throw new Exception("两次密码输入不一致");

        var user = await _userRepository.FindAsync(x => x.UserName == userRegisterDto.UserName);

        if (user != null)
            throw new Exception("用户名已存在");

        user = new User(userRegisterDto.Name, userRegisterDto.UserName, userRegisterDto.Password);

        var res = await _userRepository.InsertAsync(user);
        _logger.LogInformation($"成功注册，用户名为{userRegisterDto.UserName}");
    }

    /// <summary>
    /// 修改用户
    /// </summary>
    /// <param name="userEditDto"></param>
    /// <returns></returns>
    public async Task UpdateAsync(UserEditDto userEditDto)
    {
        var model = await _userRepository.GetAsync(x => x.Id == userEditDto.Id);
        model.Name = userEditDto.Name;
        model.UserName = userEditDto.UserName;
        model.RolesString = userEditDto.RolesString;
        await _userRepository.UpdateAsync(model);
    }
}